package com.smart.community.region.controller;

import com.smart.community.commons.utils.SecurityUtils;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.Result;
import com.smart.community.region.dto.RegionDTO;
import com.smart.community.region.dto.RegionQueryDTO;
import com.smart.community.region.dto.RegionStatsVO;
import com.smart.community.region.dto.RegionTreeVO;
import com.smart.community.region.dto.RegionVisualizationDTO;
import com.smart.community.region.entity.Region;
import com.smart.community.region.service.IRegionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.List;

/**
 * 区域管理控制器
 * 
 * @author Wu.Liang
 * @since 2024-12-21
 */
@Slf4j
@RestController
@RequestMapping("/region")
@Tag(name = "区域管理", description = "区域管理相关接口")
public class RegionController {

	@Autowired
	private IRegionService regionService;

	// ==================== 用户信息测试接口 ====================

	/**
	 * 测试用户信息获取 验证区域模块是否能正确获取网关注入的用户信息
	 */
	@GetMapping("/test/user-info")
	@Operation(summary = "测试用户信息获取", description = "验证区域模块是否能正确获取网关注入的用户信息")
	public Result<Object> testUserInfo() {
		log.info("测试用户信息获取");

		// 获取当前用户信息
		Long userId = SecurityUtils.getCurrentUserId();
		String username = SecurityUtils.getCurrentUsername();
		String userRole = SecurityUtils.getCurrentUserRole();
		String userType = SecurityUtils.getCurrentUserType();
		Long communityId = SecurityUtils.getCurrentCommunityId();
		Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();

		// 构建返回信息
		java.util.HashMap<String, Object> userInfo = new java.util.HashMap<>();
		userInfo.put("userId", userId);
		userInfo.put("username", username);
		userInfo.put("userRole", userRole);
		userInfo.put("userType", userType);
		userInfo.put("communityId", communityId);
		userInfo.put("propertyCompanyId", propertyCompanyId);
		userInfo.put("timestamp", System.currentTimeMillis());

		log.info("用户信息获取成功: {}", userInfo);
		return Result.success(userInfo);
	}

	// ==================== 基础CRUD接口 ====================

	/**
	 * 分页查询区域列表
	 * @throws Exception 
	 */
    @GetMapping
    @Operation(summary = "分页查询区域列表", description = "根据条件分页查询区域列表")
	public Result<IPage<Region>> getRegionPage(@Parameter(description = "查询条件") RegionQueryDTO queryDTO) throws Exception {
		log.info("分页查询区域列表，查询条件：{}", queryDTO);
		IPage<Region> result = regionService.getRegionPage(queryDTO);
		return Result.success(result);
	}

	/**
	 * 获取区域详情
	 */
	@GetMapping("/{regionId}")
	@Operation(summary = "获取区域详情", description = "根据区域ID获取区域详细信息")
	public Result<Region> getRegionById(@Parameter(description = "区域ID") @PathVariable Long regionId) {
		log.info("获取区域详情，区域ID：{}", regionId);
		Region region = regionService.getById(regionId);
		if (region == null) {
			return Result.error("区域不存在");
		}
		return Result.success(region);
	}

	@ApiLog(logTitle = "创建区域", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.ADD)
	@PostMapping
	@Operation(summary = "创建区域", description = "创建新的区域")
	@SaCheckPermission("region:menu")
	public Result<Boolean> createRegion(@Parameter(description = "区域信息") @RequestBody @Valid RegionDTO regionDTO)
			throws Exception {
		boolean result = regionService.createRegion(regionDTO);
		return result ? Result.success(true) : Result.error("创建区域失败");
	}

	@ApiLog(logTitle = "更新区域", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
	@PutMapping("/{regionId}")
	@Operation(summary = "更新区域", description = "更新区域信息")
	public Result<Boolean> updateRegion(@Parameter(description = "区域ID") @PathVariable Long regionId,
			@Parameter(description = "区域信息") @RequestBody @Valid RegionDTO regionDTO) throws Exception {
		regionDTO.setId(regionId);
		boolean result = regionService.updateRegion(regionDTO);
		return result ? Result.success(true) : Result.error("更新区域失败");
	}

	@ApiLog(logTitle = "删除区域", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/{regionId}")
	@Operation(summary = "删除区域", description = "删除指定区域")
	public Result<Boolean> deleteRegion(@Parameter(description = "区域ID") @PathVariable Long regionId) throws Exception {
		log.info("删除区域，区域ID：{}", regionId);
		boolean result = regionService.deleteRegion(regionId);
		return result ? Result.success(true) : Result.error("删除区域失败");
	}

	// ==================== 查询接口 ====================

	/**
	 * 根据区域编码获取区域
	 * @throws Exception 
	 */
	@GetMapping("/code/{regionCode}")
	@Operation(summary = "根据区域编码获取区域", description = "根据区域编码获取区域信息")
	public Result<Region> getRegionByCode(@Parameter(description = "区域编码") @PathVariable String regionCode) throws Exception {
		Region region = regionService.getRegionByCode(regionCode);
		if (region == null) {
			return Result.error("区域不存在");
		}
		return Result.success(region);
	}

	/**
	 * 根据区域类型获取区域列表
	 * @throws Exception 
	 */
	@GetMapping("/type/{regionType}")
	@Operation(summary = "根据区域类型获取区域列表", description = "根据区域类型获取区域列表")
	public Result<List<Region>> getRegionsByType(
			@Parameter(description = "区域类型：1-省，2-市，3-区县，4-街道，5-社区") @PathVariable Integer regionType) throws Exception {
		log.info("根据区域类型获取区域列表，区域类型：{}", regionType);
		List<Region> result = regionService.getRegionsByType(regionType);
		return Result.success(result);
	}

	/**
	 * 获取子区域列表
	 * @throws Exception 
	 */
	@GetMapping("/{regionId}/children")
	@Operation(summary = "获取子区域列表", description = "获取指定区域的子区域列表")
	public Result<List<Region>> getChildRegions(@Parameter(description = "区域ID") @PathVariable Long regionId) throws Exception {
		log.info("获取子区域列表，区域ID：{}", regionId);
		List<Region> result = regionService.getChildRegions(regionId);
		return Result.success(result);
	}

	/**
	 * 获取区域层级路径
	 * @throws Exception 
	 */
	@GetMapping("/{regionId}/path")
	@Operation(summary = "获取区域层级路径", description = "获取从根区域到指定区域的层级路径")
	public Result<List<Region>> getRegionPath(@Parameter(description = "区域ID") @PathVariable Long regionId) throws Exception {
		log.info("获取区域层级路径，区域ID：{}", regionId);
		List<Region> result = regionService.getRegionPath(regionId);
		return Result.success(result);
	}

	/**
	 * 获取区域树形结构（按需加载）
	 * @throws Exception 
	 */
	@GetMapping("/tree")
	@Operation(summary = "获取区域树形结构", description = "获取区域树形结构，支持按需加载，不传parentId获取顶级区域，传parentId获取直接子区域")
	public Result<List<RegionTreeVO>> getRegionTree(
			@Parameter(description = "父区域ID，不传则获取顶级区域") @RequestParam(required = false) Long parentId) throws Exception {
		List<RegionTreeVO> result = regionService.getRegionTree(parentId);
		return Result.success(result);
	}

	/**
	 * 获取区域完整树形结构（递归查询所有子区域）
	 * @throws Exception 
	 */
	@GetMapping("/tree/complete")
	@Operation(summary = "获取区域完整树形结构", description = "获取区域完整树形结构，递归查询所有子区域，仅用于特殊场景")
	public Result<List<RegionTreeVO>> getCompleteRegionTree(
			@Parameter(description = "父区域ID，不传则获取所有顶级区域") @RequestParam(required = false) Long parentId) throws Exception {
		List<RegionTreeVO> result = regionService.getCompleteRegionTree(parentId);
		return Result.success(result);
	}

	// ==================== 状态管理接口 ====================

	@ApiLog(logTitle = "更新区域状态", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
	@PutMapping("/{regionId}/status")
	@Operation(summary = "更新区域状态", description = "更新区域启用/禁用状态")
	public Result<Boolean> updateRegionStatus(@Parameter(description = "区域ID") @PathVariable Long regionId,
			@Parameter(description = "状态：0-禁用，1-启用") @RequestParam Integer status) throws Exception {
		boolean result = regionService.updateRegionStatus(regionId, status);
		return result ? Result.success(true) : Result.error("更新区域状态失败");
	}

	@ApiLog(logTitle = "批量更新区域状态", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
	@PutMapping("/batch/status")
	@Operation(summary = "批量更新区域状态", description = "批量更新多个区域的状态")
	public Result<Boolean> batchUpdateRegionStatus(@Parameter(description = "区域ID列表") @RequestBody List<Long> regionIds,
			@Parameter(description = "状态：0-禁用，1-启用") @RequestParam Integer status) throws Exception {
		boolean result = regionService.batchUpdateRegionStatus(regionIds, status);
		return result ? Result.success(true) : Result.error("批量更新区域状态失败");
	}

	@ApiLog(logTitle = "批量删除区域", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/batch")
	@Operation(summary = "批量删除区域", description = "批量删除多个区域")
	public Result<Boolean> batchDeleteRegions(@Parameter(description = "区域ID列表") @RequestBody List<Long> regionIds) throws Exception {
		boolean result = regionService.batchDeleteRegions(regionIds);
		return result ? Result.success(true) : Result.error("批量删除区域失败");
	}

	// ==================== 验证接口 ====================

	/**
	 * 检查区域编码唯一性
	 * @throws Exception 
	 */
	@GetMapping("/check/code")
	@Operation(summary = "检查区域编码唯一性", description = "检查区域编码是否已存在")
	public Result<Boolean> checkRegionCodeUnique(@Parameter(description = "区域编码") @RequestParam String regionCode,
			@Parameter(description = "排除的区域ID") @RequestParam(required = false) Long excludeRegionId) throws Exception {
		log.info("检查区域编码唯一性，区域编码：{}，排除区域ID：{}", regionCode, excludeRegionId);
		boolean isUnique = regionService.checkRegionCodeUnique(regionCode, excludeRegionId);
		return Result.success(isUnique);
	}

	// ==================== 统计接口 ====================

	/**
	 * 获取区域统计信息
	 * @throws Exception 
	 */
	@GetMapping("/statistics")
	@Operation(summary = "获取区域统计信息", description = "获取所有区域的统计信息")
	public Result<RegionStatsVO> getRegionStatistics() throws Exception {
		RegionStatsVO result = regionService.getRegionStatistics();
		return Result.success(result);
	}

	/**
	 * 获取指定区域统计信息
	 * @throws Exception 
	 */
	@GetMapping("/{regionId}/stats")
	@Operation(summary = "获取区域统计信息", description = "获取指定区域的统计信息")
	public Result<RegionStatsVO> getRegionStats(@Parameter(description = "区域ID") @PathVariable Long regionId) throws Exception {
		RegionStatsVO result = regionService.getRegionStats(regionId);
		return Result.success(result);
	}

	/**
	 * 获取区域统计列表
	 * @throws Exception 
	 */
	@GetMapping("/{regionId}/stats/list")
	@Operation(summary = "获取区域统计列表", description = "获取指定区域的历史统计数据")
	public Result<List<RegionStatsVO>> getRegionStatsList(@Parameter(description = "区域ID") @PathVariable Long regionId,
			@Parameter(description = "开始日期，格式：yyyy-MM-dd") @RequestParam(required = false) String startDate,
			@Parameter(description = "结束日期，格式：yyyy-MM-dd") @RequestParam(required = false) String endDate) throws Exception {
		List<RegionStatsVO> result = regionService.getRegionStatsList(regionId, startDate, endDate);
		return Result.success(result);
	}

	// ==================== 数据可视化接口 ====================

	/**
	 * 获取地图标记数据
	 * @throws Exception 
	 */
	@GetMapping("/visualization/map-markers")
	@Operation(summary = "获取地图标记数据", description = "获取区域、社区、楼栋的地图标记数据")
	public Result<List<RegionVisualizationDTO.MapMarker>> getMapMarkers(
			@Parameter(description = "标记类型：region-区域，community-社区，building-楼栋") @RequestParam(required = false) String type,
			@Parameter(description = "父区域ID") @RequestParam(required = false) Long parentId) throws Exception {
		List<RegionVisualizationDTO.MapMarker> result = regionService.getMapMarkers(type, parentId);
		return Result.success(result);
	}

	/**
	 * 获取区域面积热力图数据
	 * @throws Exception 
	 */
	@GetMapping("/visualization/area-heatmap")
	@Operation(summary = "获取区域面积热力图数据", description = "获取各区域面积分布数据，用于地图热力图展示")
	public Result<List<RegionVisualizationDTO.AreaHeatmap>> getAreaHeatmap(
			@Parameter(description = "父区域ID") @RequestParam(required = false) Long parentId) throws Exception {
		List<RegionVisualizationDTO.AreaHeatmap> result = regionService.getAreaHeatmap(parentId);
		return Result.success(result);
	}

	/**
	 * 获取区域人口统计（柱状图）
	 * @throws Exception 
	 */
	@GetMapping("/visualization/population-stats")
	@Operation(summary = "获取区域人口统计", description = "获取各区域人口统计数据，用于柱状图展示")
	public Result<List<RegionVisualizationDTO.PopulationStats>> getPopulationStats(
			@Parameter(description = "父区域ID") @RequestParam(required = false) Long parentId) throws Exception {
		List<RegionVisualizationDTO.PopulationStats> result = regionService.getPopulationStats(parentId);
		return Result.success(result);
	}

	/**
	 * 获取社区分布统计（饼图）
	 * @throws Exception 
	 */
	@GetMapping("/visualization/community-distribution")
	@Operation(summary = "获取社区分布统计", description = "获取社区分布数据，用于饼图展示")
	public Result<List<RegionVisualizationDTO.CommunityDistribution>> getCommunityDistribution(
			@Parameter(description = "父区域ID") @RequestParam(required = false) Long parentId) throws Exception {
		List<RegionVisualizationDTO.CommunityDistribution> result = regionService.getCommunityDistribution(parentId);
		return Result.success(result);
	}

	// ==================== 地理信息接口 ====================

	/**
	 * 地理信息查询
	 * @throws Exception 
	 */
	@GetMapping("/geo-query")
	@Operation(summary = "地理信息查询", description = "根据经纬度范围查询区域信息")
	public Result<List<Region>> geoQuery(@Parameter(description = "最小纬度") @RequestParam BigDecimal minLat,
			@Parameter(description = "最大纬度") @RequestParam BigDecimal maxLat,
			@Parameter(description = "最小经度") @RequestParam BigDecimal minLng,
			@Parameter(description = "最大经度") @RequestParam BigDecimal maxLng) throws Exception {
		List<Region> result = regionService.geoQuery(minLat, maxLat, minLng, maxLng);
		return Result.success(result);
	}

	// ==================== 缓存管理接口 ====================

	@ApiLog(logTitle = "清除区域缓存", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/cache/{regionId}")
	@Operation(summary = "清除区域缓存", description = "清除指定区域的缓存")
	public Result<Boolean> clearRegionCache(@Parameter(description = "区域ID") @PathVariable Long regionId) throws Exception {
		regionService.clearRegionCache(regionId);
		return Result.success(true);
	}

	@ApiLog(logTitle = "清除所有区域缓存", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/cache/all")
	@Operation(summary = "清除所有区域缓存", description = "清除所有区域相关的缓存")
	public Result<Boolean> clearAllRegionCache() throws Exception {
		regionService.clearAllRegionCache();
		return Result.success(true);
	}

	/**
	 * 刷新区域统计数据
	 * @throws Exception 
	 */
	@PostMapping("/{regionId}/refresh-stats")
	@Operation(summary = "刷新区域统计数据", description = "手动刷新指定区域的统计数据")
	public Result<Boolean> refreshRegionStats(@Parameter(description = "区域ID") @PathVariable Long regionId) throws Exception {
		boolean result = regionService.refreshRegionStats(regionId);
		return result ? Result.success(true) : Result.error("刷新区域统计数据失败");
	}
}